<?php

/*
 * 京东快递处理
 */

class Jd {

    /**
     * @var string 应用KEY
     */
    private $appKey = '943FEBA098B82AC8962E6CD9E0CC3525';

    /**
     * @var string 应用SECRET
     */
    private $appSecret = 'cb22a35cb2c94c3e9df9420a5cbd2625';

    /**
     * @var string 接口必需OAUTH的token
     */
    private $accessToken = '3d7f3126-49c6-404b-a4fa-e462ce235112';

    /**
     * @var string 接口地址 
     */
    private $serverUrl = 'https://api.jd.com/routerjson';

    /**
     * @var string 商家正向编号
     */
    protected $positiveCustomerCode = '021K190300';

    /**
     * @var string 商家反向编号
     */
    protected $reverseCustomerCode = '021K190138';
    protected $fd = '';

    /**
     * @var type 
     */
    protected $client;

    /**
     * @var type 
     */
    protected $error;

    /**
     * 创建对象
     */
    public function __construct() {
        if (!defined('JD_SDK_WORK_DIR')) {
            define("JD_SDK_WORK_DIR", __DIR__ . "/tmp/");
            define("JD_SDK_DEV_MODE", true);
            spl_autoload_register(function($class) {
                foreach ([__DIR__ . DS . 'jd', __DIR__ . DS . 'jd' . DS . 'request'] as $dir) {
                    $file = $dir . DS . str_replace('\\', DS, $class) . '.php';
                    if (file_exists($file)) {
                        think\__require_file($file);
                        return true;
                    }
                }
                return false;
            });
        }
        $this->client = new JdClient();
        $this->client->appKey = $this->appKey;
        $this->client->appSecret = $this->appSecret;
        $this->client->accessToken = $this->accessToken;
        $this->client->serverUrl = $this->serverUrl;
    }

    /**
     * 获取错误内容
     * @return string
     */
    public function getError() {
        return (string) $this->error;
    }

    /**
     * 运单拦截
     * @param string $deliveryId 运单号
     * @param string $interceptReason 拦截原因
     * @param bool $isPositive 是否为正向发货物流
     * @return bool
     */
    public function interception($deliveryId, $interceptReason, $isPositive = false) {
        $req = new LdopReceiveOrderInterceptRequest();
        $req->setVendorCode($isPositive ? $this->positiveCustomerCode : $this->reverseCustomerCode);
        $req->setDeliveryId($deliveryId);
        $req->setInterceptReason($interceptReason);
        $resp = $this->client->execute($req, $this->client->accessToken);
        if (isset($resp['resultInfo']['stateCode']) && $resp['resultInfo']['stateCode'] == 100) {
            return true;
        } elseif (isset($resp['resultInfo']['stateMessage'])) {
            $this->error = $resp['resultInfo']['stateMessage'];
        }
        return false;
    }

    /**
     * 异常单审核
     * @param string $deliveryId 运单号  
     * @param string $responseComment 返回描述
     * @param int $type 异常处理结果（1：再投，2：退回，3：站点报废）
     * @param bool $isPositive 是否为正向发货物流
     * @return bool
     */
    public function abnormity($deliveryId, $responseComment, $type, $isPositive = false) {
        $req = new LdopAbnormalApprovalRequest();
        $req->setCustomerCode($isPositive ? $this->positiveCustomerCode : $this->reverseCustomerCode);
        $req->setDeliveryId($deliveryId);
        $req->setResponseComment($responseComment);
        $req->setType($type);
        $resp = $this->client->execute($req, $this->client->accessToken);
        if (isset($resp['approval_result']['stateCode']) && $resp['approval_result']['stateCode'] == 100) {
            return true;
        } elseif (isset($resp['approval_result']['stateMessage'])) {
            $this->error = $resp['approval_result']['stateMessage'];
        }
        return false;
    }

    /**
     * 查询拒收再投单
     * @param bool $isPositive 是否为正向发货物流
     * @return boolean
     */
    public function abnormal($isPositive = false) {
        $req = new LdopAbnormalGetRequest();
        $req->setCustomerCode($isPositive ? $this->positiveCustomerCode : $this->reverseCustomerCode);
        $resp = $this->client->execute($req, $this->client->accessToken);
        if (isset($resp['querybycondition_result']['stateCode']) && $resp['querybycondition_result']['stateCode'] == 100) {
            return true;
        } elseif (isset($resp['querybycondition_result']['stateMessage'])) {
            $this->error = $resp['querybycondition_result']['stateMessage'];
        }
        return false;
    }

    /**
     * 预约取件处理
     * @param string $orderId 订单号
     * @param string $pickupName 取件联系人
     * @param string $pickupAddress 取件地址
     * @param string $pickupTel 取件联系电话
     * @return boolean|string 成功返回取件单号
     */
    public function pickup($orderId, $pickupName, $pickupAddress, $pickupTel, $pickupStartTime = null) {
        return $this->receive($pickupAddress, $pickupName, $pickupTel, '0571-86113050', '浙江省杭州市余杭区仓前街道龙潭路7号未来研创园A幢307室', '孙杰', $orderId, $pickupStartTime);
    }

    /**
     * 取件单下单，反向用户归还取件
     * @param string $pickupAddress 取件地址
     * @param string $pickupName 取件联系人
     * @param string $pickupTel 取件联系电话
     * @param string $customerTel 商家联系电话
     * @param string $backAddress 退货地址
     * @param string $customerContract 商家联系人
     * @param string $desp 取件描述
     * @param string $orderId 订单号
     * @param float $weight 重量
     * @param string $remark 备注
     * @param float $volume 体积
     * @param string $valueAddService 增值服务
     * @param string $pickupStartTime 开始取件时间 Y-m-d H:i:s
     * @param string $pickupEndTime 结束取件时间 Y-m-d H:i:s
     * @param boolean $guaranteeValue 是否保价
     * @param float $guaranteeValueAmount 保价金额
     * @return boolean|string 成功返回取件单号
     */
    public function receive($pickupAddress, $pickupName, $pickupTel, $customerTel, $backAddress, $customerContract, $orderId, $pickupStartTime = null, $desp = '归还绘本', $remark = '归还绘本', $weight = 1, $volume = 100, $pickupEndTime = null) {
        $req = new LdopReceivePickuporderReceiveRequest();
        $req->setPickupAddress($pickupAddress);
        $req->setPickupName($pickupName);
        $req->setPickupTel($pickupTel);
        $req->setCustomerTel($customerTel);
        $req->setCustomerCode($this->reverseCustomerCode);
        $req->setBackAddress($backAddress);
        $req->setCustomerContract($customerContract);
        $req->setDesp($desp);
        $req->setOrderId($orderId);
        $req->setWeight($weight);
        $req->setRemark($remark);
        $req->setVolume($volume);
//        $req->setValueAddService($valueAddService);
//        $req->setGuaranteeValue($guaranteeValue);
//        $req->setGuaranteeValueAmount($guaranteeValueAmount);
        $pickupStartTime && $req->setPickupStartTime($pickupStartTime);
        $pickupEndTime && $req->setPickupEndTime($pickupEndTime);
        $resp = $this->client->execute($req, $this->client->accessToken);
        if (isset($resp['receivepickuporder_result']['code']) && $resp['receivepickuporder_result']['code'] == 100) {
            return $resp['receivepickuporder_result']['pickUpCode'];
        } elseif (isset($resp['receivepickuporder_result']['messsage'])) {
            $this->error = $resp['receivepickuporder_result']['messsage'];
        }
        return false;
    }

    /**
     * 查询物流信息
     * @param string $waybillCode 运单号
     * @param bool $isPositive 是否为正向发货物流
     * @return boolean|array
     */
    public function search($waybillCode, $isPositive = false) {
        $req = new LdopReceiveTraceGetRequest();
        $req->setCustomerCode($isPositive ? $this->positiveCustomerCode : $this->reverseCustomerCode); //商家编码
        $req->setWaybillCode($waybillCode); //运单号
        $resp = $this->client->execute($req, $this->client->accessToken);
        if (isset($resp['querytrace_result']['code']) && $resp['querytrace_result']['code'] == 100) {
            return $resp['querytrace_result']['data'];
        } elseif (isset($resp['querytrace_result']['messsage'])) {
            $this->error = $resp['querytrace_result']['messsage'];
        }
        return false;
    }

    /**
     * 预约发货
     * @param string $orderId 订单号
     * @param string $receiveName 收件人名称
     * @param string $receiveAddress 收件人地址
     * @param string $receiveMobile 收件人手机号
     * @return boolean|array
     */
    public function bespoke($orderId, $receiveName, $receiveAddress, $receiveMobile) {
        return $this->send('0030001', $orderId, '孙杰', '浙江省杭州市余杭区仓前街道龙潭路7号未来研创园A幢307室', '0571-86113050', $receiveName, $receiveAddress, $receiveMobile);
    }

    /**
     * 京东物流接单接口
     * @param string $salePlat 销售平台
     * @param string $orderId 订单号
     * @param string $thrOrderId 销售平台订单号(例如京东订单号或天猫订单号等等。总长度不要超过100。如果有多个单号，用英文,间隔。例如：7898675,7898676) 
     * @param string $senderName 寄件人姓名
     * @param string $senderAddress 寄件人地址
     * @param string $senderTel 寄件人电话
     * @param string $senderMobile 寄件人手机(寄件人电话、手机至少有一个不为空)
     * @param string $senderPostcode 寄件人邮编
     * @param string $receiveName 收件人名称
     * @param string $receiveAddress 收件人地址
     * @param string $province 收件人省
     * @param string $city 收件人市
     * @param string $county 收件人县
     * @param string $town 收件人镇
     * @param int $provinceId 收件人省编码
     * @param int $cityId 收件人市编码
     * @param int $countyId 收件人县编码
     * @param int $townId 收件人镇编码
     * @param int $siteType 站点类型
     * @param int $siteId 站点编码
     * @param string $siteName 站点名称
     * @param string $receiveTel 收件人电话
     * @param string $receiveMobile 收件人手机号(收件人电话、手机至少有一个不为空)
     * @param string $postcode 收件人邮编
     * @param int $packageCount 包裹数(大于0，小于1000) 
     * @param float $weight 重量(单位：kg，保留小数点后两位)
     * @param float $vloumLong 包裹长(单位：cm,保留小数点后两位)
     * @param float $vloumWidth 包裹宽(单位：cm，保留小数点后两位)
     * @param float $vloumHeight 包裹高(单位：cm，保留小数点后两位)
     * @param float $vloumn 体积(单位：cm3，保留小数点后两位)
     * @param string $description 商品描述
     * @param int $collectionValue 是否代收货款(是：1，否：0。不填或者超出范围，默认是0)  
     * @param float $collectionMoney 代收货款金额(保留小数点后两位)
     * @param int $guaranteeValue 是否保价(是：1，否：0。不填或者超出范围，默认是0) 
     * @param float $guaranteeValueAmount 保价金额(保留小数点后两位)  
     * @param int $signReturn 签单返还(是：1，否：0。不填或者超出范围，默认是0)
     * @param int $aging 时效(普通：1，工作日：2，非工作日：3，晚间：4。O2O一小时达：5。O2O定时达：6。不填或者超出范围，默认是1)  
     * @param int $transType 运输类型(陆运：1，航空：2。不填或者超出范围，默认是1)  
     * @param string $remark 运单备注（不超过20个字）,打印面单时备注内容也会显示在快递面单上
     * @param int $goodsType 配送业务类型（ 1:普通，3:填仓，4:特配，6:控温，7:冷藏，8:冷冻，9:深冷）默认是1
     * @param int $orderType 运单类型。(普通外单：0，O2O外单：1)默认为0
     * @param string $shopCode 门店编码(只O2O运单需要传，普通运单不需要传)
     * @param string $orderSendTime 预约配送时间（格式：yyyy-MM-dd HH:mm:ss。例如：2014-09-18 08:30:00）
     * @param string $warehouseCode 发货仓编码
     * @param int $areaProvId 接货省ID
     * @param int $areaCityId 接货市ID
     * @param string $shipmentStartTime 配送起始时间
     * @param string $shipmentEndTime 配送结束时间
     * @param string $idNumber 身份证号
     * @param string $addedService 扩展服务
     * @param string $extendField1 扩展字段1
     * @param string $extendField2 扩展字段2
     * @param string $extendField3 扩展字段3
     * @param int $extendField4 扩展字段4
     * @param int $extendField5 扩展字段5
     * @return boolean|array
     */
    public function send($salePlat, $orderId, $senderName, $senderAddress, $senderMobile, $receiveName, $receiveAddress, $receiveMobile, $packageCount = 1, $weight = 1.5, $vloumn = 100, $description = '绘本图书', $remark = '') {
        $req = new LdopWaybillReceiveRequest();
        $req->setSalePlat($salePlat); //销售平台
        $req->setCustomerCode($this->positiveCustomerCode); //商家编码
        $req->setOrderId($orderId); //订单号
//        $req->setThrOrderId($thrOrderId);//销售平台订单号
        $req->setSenderName($senderName); //寄件人姓名
        $req->setSenderAddress($senderAddress); //寄件人地址
//        $req->setSenderTel($senderTel); //寄件人电话
        $req->setSenderMobile($senderMobile); //寄件人手机
//        $req->setSenderPostcode($senderPostcode); //寄件人邮编
        $req->setReceiveName($receiveName); //收件人名称
        $req->setReceiveAddress($receiveAddress); //收件人地址
//        $req->setProvince($province); //收件人省
//        $req->setCity($city); //收件人市
//        $req->setCounty($county); //收件人县
//        $req->setTown($town); //收件人镇
//        $req->setProvinceId($provinceId); //收件人省编码
//        $req->setCityId($cityId); //收件人市编码
//        $req->setCountyId($countyId); //收件人县编码
//        $req->setTownId($townId); //收件人镇编码
//        $req->setSiteType($siteType); //站点类型
//        $req->setSiteId($siteId); //站点编码
//        $req->setSiteName($siteName); //站点名称
//        $req->setReceiveTel($receiveTel); //收件人电话
        $req->setReceiveMobile($receiveMobile); //收件人手机号
//        $req->setPostcode($postcode); //收件人邮编
        $req->setPackageCount($packageCount); //包裹数
        $req->setWeight($weight); //重量
//        $req->setVloumLong($vloumLong); //包裹长
//        $req->setVloumWidth($vloumWidth); //包裹宽
//        $req->setVloumHeight($vloumHeight); //包裹高
        $req->setVloumn($vloumn); //体积
        $req->setDescription($description); //商品描述
//        $req->setCollectionValue($collectionValue); //是否代收货款
//        $req->setCollectionMoney($collectionMoney); //代收货款金额
//        $req->setGuaranteeValue($guaranteeValue); //是否保价
//        $req->setGuaranteeValueAmount($guaranteeValueAmount); //保价金额
//        $req->setSignReturn($signReturn); //签单返还
//        $req->setAging($aging); //时效
//        $req->setTransType($transType); //运输类型
        $req->setRemark($remark); //运单备注
//        $req->setGoodsType($goodsType); //配送业务类型
//        $req->setOrderType($orderType); //运单类型
//        $req->setShopCode($shopCode); //门店编码
//        $req->setOrderSendTime($orderSendTime); //预约配送时间
        $req->setWarehouseCode('02006'); //发货仓编码
//        $req->setAreaProvId($areaProvId); //接货省ID
//        $req->setAreaCityId($areaCityId); //接货市ID
//        $req->setShipmentStartTime($shipmentStartTime); //配送起始时间
//        $req->setShipmentEndTime($shipmentEndTime); //配送结束时间
//        $req->setIdNumber($idNumber); //身份证号
//        $req->setAddedService($addedService); //扩展服务
//        $req->setExtendField1($extendField1); //扩展字段1
//        $req->setExtendField2($extendField2); //扩展字段2
//        $req->setExtendField3($extendField3); //扩展字段3
//        $req->setExtendField4($extendField4); //扩展字段4
//        $req->setExtendField5($extendField5); //扩展字段5
        $resp = $this->client->execute($req, $this->client->accessToken);
        if (isset($resp['receiveorderinfo_result']['resultCode']) && $resp['receiveorderinfo_result']['resultCode'] == 100) {
            return [
                'orderId' => $orderId,
                'deliveryId' => $resp['receiveorderinfo_result']['deliveryId'],
                'preSortResult' => $resp['receiveorderinfo_result']['preSortResult']
            ];
        } elseif (isset($resp['receiveorderinfo_result']['resultMessage'])) {
            $this->error = $resp['receiveorderinfo_result']['resultMessage'];
        }
        return false;
    }

}
